package io.adminboot.quartz.service.impl;

import io.adminboot.quartz.domain.JobInputDTO;
import io.adminboot.quartz.domain.JobOutputDTO;
import io.adminboot.quartz.entity.QuartzEntity;
import io.adminboot.quartz.exception.JobServiceException;
import io.adminboot.quartz.repository.JobMapper;
import io.adminboot.quartz.service.IQuartzService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service("quartzService")
public class QuartzServiceImpl implements IQuartzService {

    private final static Logger logger = LoggerFactory.getLogger(QuartzServiceImpl.class);

    @Autowired
    @Qualifier("Scheduler")
    private Scheduler scheduler;

    @Autowired
    private JobMapper jobMapper;

    @Override
    public void add(JobInputDTO dto) throws JobServiceException {
        try {
            Class cls = Class.forName(dto.getJobClassName());
            cls.newInstance();
            //构建job信息
            final String jobName = dto.getJobName();
            final String groupName = dto.getGroupName();
            JobDetail job = JobBuilder.newJob(cls).withIdentity(jobName, groupName)
                    .withDescription(dto.getDescp()).build();
            // 触发时间点
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(dto.getCronExpression());
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger" + jobName, groupName)
                    .startNow().withSchedule(cronScheduleBuilder).build();
            //交由Scheduler安排触发
            scheduler.scheduleJob(job, trigger);
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | SchedulerException e) {
            final String msg = "Job新增失败:";
            logger.error("Job新增失败:jobName={}, groupName={}", dto.getJobName(), dto.getGroupName());
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void trigger(String jobName, String groupName) throws JobServiceException {
        try {
            JobKey key = new JobKey(jobName, groupName);
            scheduler.triggerJob(key);
        } catch (SchedulerException e) {
            final String msg = "Job触发失败";
            logger.error("Job触发失败:jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void pause(String jobName, String groupName) throws JobServiceException {
        try {
            JobKey key = new JobKey(jobName, groupName);
            scheduler.pauseJob(key);
        } catch (SchedulerException e) {
            final String msg = "Job暂停败";
            logger.error("Job暂停失败:jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void resume(String jobName, String groupName) throws JobServiceException {
        try {
            JobKey key = new JobKey(jobName, groupName);
            scheduler.resumeJob(key);
        } catch (SchedulerException e) {
            final String msg = "Job恢复失败";
            logger.error("Job恢复失败:jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public void remove(String jobName, String groupName) throws JobServiceException {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(jobName, groupName));
        } catch (Exception e) {
            final String msg = "Job暂停败";
            logger.error("Job删除失败:jobName={}, groupName={}", jobName, groupName);
            logger.error("" + e);
            throw new JobServiceException(msg, e);
        }
    }

    @Override
    public List<JobOutputDTO> list(String jobName) {
        List<JobOutputDTO> result = new ArrayList<>();
        final List<QuartzEntity> quartzEntities = jobMapper.selectList(jobName);
        if (CollectionUtils.isEmpty(quartzEntities)) {
            return result;
        }
        return quartzEntities.stream().map(this::wrapDTO).collect(Collectors.toList());
    }

    /**
     * 封装DTO
     *
     * @param quartzEntity
     * @return
     */
    private JobOutputDTO wrapDTO(QuartzEntity quartzEntity) {
        return new JobOutputDTO(quartzEntity);
    }

    @Override
    public Long count() {
        return jobMapper.count();
    }
}
